package com.infolab.aims.web;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.infolab.aims.GlobalConstant;
import com.infolab.aims.common.AbstractController;
import com.infolab.aims.common.InQueryHelper;
import com.infolab.aims.common.bean.SearchCriteria;
import com.infolab.aims.domain.Department;
import com.infolab.aims.domain.Driver;
import com.infolab.aims.domain.Report;
import com.infolab.aims.domain.Section;
import com.infolab.aims.domain.SystemCodeType;
import com.infolab.aims.domain.SystemCodeValue;
import com.infolab.aims.domain.SystemUser;
import com.infolab.aims.domain.Vehicle;
import com.infolab.aims.domain.asset.AssetEquipment;
import com.infolab.aims.domain.asset.AssetModel;
import com.infolab.aims.domain.workorder.WorkOrder;
import com.infolab.aims.domain.workorder.WorkOrderAdHoc;
import com.infolab.aims.service.intf.AssetModelService;
import com.infolab.aims.service.intf.ReportService;
import com.infolab.aims.service.intf.SystemCodeService;
import com.infolab.aims.service.intf.SystemUserService;
import com.infolab.aims.service.intf.VehicleService;
import com.infolab.aims.service.intf.VendorService;
import com.infolab.aims.service.intf.WorkOrderAdHocService;
import com.infolab.aims.service.intf.WorkOrderServiceFacade;
import com.infolab.aims.web.form.WorkOrderWeek;


@Controller
@RequestMapping("/ajax")
public class AjaxController extends AbstractController {

	@Autowired
	AssetModelService assetModelService;
	
	@Autowired
	VehicleService vehicleService;
	
	@Autowired
	WorkOrderAdHocService workOrderAdHocService;
	
	@Autowired
	WorkOrderServiceFacade workOrderServiceFacade;
	
	@Autowired
	SystemUserService systemUserService;
	
	@Autowired
	SystemCodeService systemCodeService;
	
	@Autowired
	VendorService vendorService;
	
	@Autowired
	ReportService reportService;
	
	public final Integer MAX_ROW = 100;
	
	Log logger = LogFactory.getLog(getClass());
	
	@RequestMapping(method=RequestMethod.GET)
	public @ResponseBody String notFound()
	{
		return "[]";
	}
	
	@RequestMapping(value="section/{departmentId}", method = RequestMethod.GET)
	public @ResponseBody List<Section> showSection(@PathVariable String departmentId) {
		if(StringUtils.isNumeric(departmentId))
		{
			List list = commonService.getSection(Integer.valueOf(departmentId));
			return list ;
		}
		else
			return new ArrayList<Section>();
	}
	
	@RequestMapping(value="role/{sectionId}", method = RequestMethod.GET)
	public @ResponseBody List<Section> showRole(@PathVariable String sectionId) {
		if(StringUtils.isNumeric(sectionId))
		{
			List list = commonService.getRole(Integer.valueOf(sectionId));
			return list ;
		}
		else
			return new ArrayList<Section>();
		
	}
	
	@RequestMapping(value="asset/equipment", method = RequestMethod.GET)
	public @ResponseBody List<AssetModel> showAssetEquipment() {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("assetType", AssetModel.ASSETTYPE_EQUIPMENT);
		
		List<AssetModel> assetModels = assetModelService.findAssetModels(searchCriteria);
		return assetModels;
		
	}
	
	@RequestMapping(value="asset/component", method = RequestMethod.GET)
	public @ResponseBody List<AssetModel> showAssetComponent() {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("assetType", AssetModel.ASSETTYPE_COMPONENT);
		List<AssetModel> assetModels = assetModelService.findAssetModels(searchCriteria);
		return assetModels;
	}
	
	@RequestMapping(value="equipment/faulty", method = RequestMethod.GET)
	public @ResponseBody List<AssetEquipment> showFaultyEquipment(@RequestParam(value="assetModelId",required=false) Integer assetModelId,@RequestParam(value="locationId",required=false) Integer locationId,@RequestParam(value="serialNo",required=false) String serialNo,@RequestParam(value="companyCode",required=false) String companyCode) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("assetEquipmentStatus", AssetModel.ASSETSTATUS_FAULT);
		if(assetModelId!=null)
			searchCriteria.addSearchCriteria("assetModelId", assetModelId);
		if(locationId!=null)
			searchCriteria.addSearchCriteria("locationId", locationId);
		if(serialNo!=null)
			searchCriteria.addSearchCriteria("serialNo", serialNo);
		if(companyCode!=null)
			searchCriteria.addSearchCriteria("companyCode", companyCode);
		
		searchCriteria.setMaxRow(MAX_ROW);
		
		List<AssetEquipment> assetEquipments = assetModelService.findAssetEquipments(searchCriteria);
		
		return assetEquipments;
		
	}
	
	@RequestMapping(value="equipment/active", method = RequestMethod.GET)
	public @ResponseBody List<AssetEquipment> showActiveEquipment(@RequestParam(value="assetModelId",required=false) Integer assetModelId,@RequestParam(value="locationId",required=false) Integer locationId,@RequestParam(value="serialNo",required=false) String serialNo,@RequestParam(value="companyCode",required=false) String companyCode) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("assetEquipmentStatus", AssetModel.ASSETSTATUS_ACTIVE);
		if(assetModelId!=null)
			searchCriteria.addSearchCriteria("assetModelId", assetModelId);
		if(locationId!=null)
			searchCriteria.addSearchCriteria("locationId", locationId);
		if(serialNo!=null)
			searchCriteria.addSearchCriteria("serialNo", serialNo);
		if(companyCode!=null)
			searchCriteria.addSearchCriteria("companyCode", companyCode);
		
		searchCriteria.setMaxRow(MAX_ROW);
		List<AssetEquipment> assetEquipments = assetModelService.findAssetEquipments(searchCriteria);
		return assetEquipments;
		
	}
	
	@RequestMapping(value="equipment/workOrder", method = RequestMethod.GET)
	public @ResponseBody List<AssetEquipment> showWorkOrderActiveSerialNo(@RequestParam(value="assetModelId",required=false) Integer assetModelId,@RequestParam(value="q",required=false) String q) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("systemCodeTypeCode", GlobalConstant.SYSTEM_CODE_TYPE_WORKORDER_ACTIVE_LOCATION);
		List<SystemCodeType> systemCodeTypes = systemCodeService.findSystemCodeTypes(searchCriteria);
		SystemCodeType systemCodeType = systemCodeTypes.get(0);
		
		//TODO: temporary to allow them to search serial no in dummy and in vehicle
		InQueryHelper helper = new InQueryHelper("locationCode", Arrays.asList(new String[]{systemCodeType.getSystemCodeTypeValue(),"PV","XXX"}));
		searchCriteria.addSearchCriteria("locationCode", helper);
		
		//searchCriteria.addSearchCriteria("locationCode", systemCodeType.getSystemCodeTypeValue());
		searchCriteria.addSearchCriteria("assetEquipmentStatus", AssetModel.ASSETSTATUS_ACTIVE);
		searchCriteria.setMaxRow(MAX_ROW);
		
		if(assetModelId!=null)
			searchCriteria.addSearchCriteria("assetModelId", assetModelId);
		if(q!=null)
			searchCriteria.addSearchCriteria("serialNo", q);
		
		List<AssetEquipment> assetEquipments = assetModelService.findAssetEquipments(searchCriteria);
		return assetEquipments;
		
	}
	
	@RequestMapping(value="serialno/availability", method = RequestMethod.GET)
	public @ResponseBody Boolean checkSerialNoAvailability(@RequestParam(value="serialNo",required=true) String serialNo) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("serialNo", serialNo);
		
		AssetEquipment assetEquipment = assetModelService.findAssetEquipment(searchCriteria);
		
		return assetEquipment==null;
		
	}
	

	@RequestMapping(value="asset/all", method = RequestMethod.GET)
	public @ResponseBody List<AssetModel> showAssetAll() {
		SearchCriteria searchCriteria = new SearchCriteria();
		List<AssetModel> assetModels = assetModelService.findAssetModels(searchCriteria);
		return assetModels;
	}
	
	@RequestMapping(value="vendorPrice", method = RequestMethod.GET)
	public @ResponseBody List<AssetModel> showVendorPrice(@RequestParam(value="vendorId",required=true) Integer vendorId,@RequestParam(value="assetType",required=true) String assetType) {
		List<AssetModel> assetModels = vendorService.findAssetModelsPrice(assetType, vendorId);
		return assetModels;
	}
	
	
	@RequestMapping(value="populateAssetTransType", method = RequestMethod.GET)
	public @ResponseBody HashMap populateAssetTransType(@RequestParam(value="assetType") String assetType) {
		
		HashMap assetTransTypes= new HashMap();
		
		if(assetType.equalsIgnoreCase("COMPONENT"))
		{
			assetTransTypes.put("", "");
			assetTransTypes.put("IO", "Issue Order & Component");
			assetTransTypes.put("SAJ", "Stock Adjustment - Component");
			assetTransTypes.put("DO", "Received in by Purchase Order");	
		}
		
		else if(assetType.equalsIgnoreCase("EQUIPMENT"))
		{
			assetTransTypes.put("", "");
			assetTransTypes.put("ET-SOI", "Equipment Transfer");
			assetTransTypes.put("FT", "Faulty Equipment Transfer");
			assetTransTypes.put("SCRAP", "Scrap ");
			assetTransTypes.put("SAJ", "Stock Adjustment");	
			assetTransTypes.put("POR-DOR", "Issue to third party");	
			assetTransTypes.put("DO", "Received in by Purchase Order");	
		}
		
		else
		{
			assetTransTypes.put("", "");
			assetTransTypes.put("IO", "Issue Order �Component");
			assetTransTypes.put("ET-SOI", "Equipment Transfer");
			assetTransTypes.put("FT", "Faulty Equipment Transfer");
			assetTransTypes.put("SCRAP", "Scrap ");
			assetTransTypes.put("SAJ", "Stock Adjustment");
			assetTransTypes.put("POR-DOR", "Issue to third party");
			assetTransTypes.put("DO", "Received in by Purchase Order");				
		}
		return assetTransTypes;		
	}
	
	@RequestMapping(value="vehicle", method = RequestMethod.GET)
	public @ResponseBody List<Vehicle> showVehicle(@RequestParam(value="q") String id) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("vehicleId", id);
		searchCriteria.setSortType(SearchCriteria.SORTTYPE_ASC);
		searchCriteria.setSortName("vehicleId");
		searchCriteria.setMaxRow(MAX_ROW);
		List<Vehicle> list= vehicleService.findVehicles(searchCriteria);
		
		List<Vehicle> compact = new ArrayList<Vehicle>();
		if(list!=null)
		{
			for(int i=0;i<list.size();i++)
			{
				Vehicle tmp = list.get(i);
				Vehicle vehicle = new Vehicle();
				vehicle.setVehicleId(tmp.getVehicleId());
				vehicle.setDriverName(tmp.getDriverName());
				vehicle.setDriverNric(tmp.getDriverNric());
				vehicle.setDriverTelephoneNo(tmp.getDriverTelephoneNo());
				vehicle.setDriverType(tmp.getDriverType());
				vehicle.setMeVersion(tmp.getMeVersion());
				vehicle.setDriverEmail(tmp.getDriverEmail());
				vehicle.setAssetModelCode(tmp.getAssetModelCode());
				vehicle.setCompanyCode(tmp.getCompanyCode());
				
				compact.add(vehicle);
			}
		}
		return compact;
	}
	
	@RequestMapping(value="vehiclePart/{vehicleId}", method = RequestMethod.GET)
	public @ResponseBody List<Vehicle> showVehiclePart(@PathVariable String vehicleId) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("vehicleId", vehicleId);
		searchCriteria.setSortName("vehicleId");
		
		Vehicle vehicle = vehicleService.findVehicle(searchCriteria);
		
		return null;
	}
	
	
	@RequestMapping(value="driver/{vehicleId}", method = RequestMethod.GET)
	public @ResponseBody List<Driver> showDriver(@PathVariable String vehicleId) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("vehicleId", vehicleId);
		searchCriteria.setSortName("vehicleId");
		
		List<Driver> drivers = vehicleService.findDrivers(searchCriteria);
		
		return drivers;
	}
	
	@RequestMapping(value="adHoc/{vehicleId}", method = RequestMethod.GET)
	public @ResponseBody List<WorkOrderAdHoc> showAdHoc(@PathVariable String vehicleId) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("vehicleId", vehicleId);
		searchCriteria.addSearchCriteria("adHocStatus", WorkOrderAdHoc.ADHOCSTATUS_NEW);
		List<WorkOrderAdHoc> list = workOrderAdHocService.findWorkOrderAdHocs(searchCriteria);
		
		List<WorkOrderAdHoc> compact = new ArrayList<WorkOrderAdHoc>();
		if(list!=null)
		{
			for(int i=0;i<list.size();i++)
			{
				WorkOrderAdHoc tmp = list.get(i);
				WorkOrderAdHoc workOrderAdHoc = new WorkOrderAdHoc();
				workOrderAdHoc.setWorkOrderAdHocId(tmp.getWorkOrderAdHocId());
				workOrderAdHoc.setWorkOrder(tmp.getWorkOrder());
				workOrderAdHoc.setSystemCodeValue(tmp.getSystemCodeValue());
				
				workOrderAdHoc.setAppointmentDate(tmp.getAppointmentDate());
				workOrderAdHoc.setAdHocRemarks(tmp.getAdHocRemarks());
				workOrderAdHoc.setAdHocStatus(tmp.getAdHocStatus());
				
				compact.add(workOrderAdHoc);
			}
		}
		return compact;
	}
	
	@RequestMapping(value="faultCode", method = RequestMethod.GET)
	public @ResponseBody List<SystemCodeValue> showFaultCode(@RequestParam(value="q",required=false) String faultCodeDescription) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("systemCodeTypeCode", GlobalConstant.SYSTEM_CODE_TYPE_FAULT_CODE);
		//searchCriteria.addSearchCriteria("systemCodeValueDescription", faultCodeDescription);
		List<SystemCodeValue> list = systemCodeService.findSystemCodeCodeValues(searchCriteria);
		
		List<SystemCodeValue> compact = new ArrayList<SystemCodeValue>();
		if(list!=null)
		{
			for(int i=0;i<list.size();i++)
			{
				SystemCodeValue tmp = list.get(i);
				SystemCodeValue systemCodeValue = new SystemCodeValue();
				systemCodeValue.setSystemCodeValueId(tmp.getSystemCodeValueId());
				systemCodeValue.setSystemCode1(tmp.getSystemCode1());
				systemCodeValue.setSystemCodeValueDescription(tmp.getSystemCodeValueDescription());
				
				compact.add(systemCodeValue);
			}
		}
		return compact;
	}
	
	@RequestMapping(value="repairCode", method = RequestMethod.GET)
	public @ResponseBody List<SystemCodeValue> showRepairCode(@RequestParam(value="q",required=false) String faultCodeDescription) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("systemCodeTypeCode", GlobalConstant.SYSTEM_CODE_TYPE_REPAIR_CODE);
		//searchCriteria.addSearchCriteria("systemCodeValueDescription", faultCodeDescription);
		List<SystemCodeValue> list = systemCodeService.findSystemCodeCodeValues(searchCriteria);
		
		List<SystemCodeValue> compact = new ArrayList<SystemCodeValue>();
		if(list!=null)
		{
			for(int i=0;i<list.size();i++)
			{
				SystemCodeValue tmp = list.get(i);
				SystemCodeValue systemCodeValue = new SystemCodeValue();
				systemCodeValue.setSystemCodeValueId(tmp.getSystemCodeValueId());
				systemCodeValue.setSystemCode1(tmp.getSystemCode1());
				systemCodeValue.setSystemCodeValueDescription(tmp.getSystemCodeValueDescription());
				
				compact.add(systemCodeValue);
			}
		}
		
		return compact;
	}
	
	@RequestMapping(value="technician", method = RequestMethod.GET)
	public @ResponseBody List<SystemUser> showTechnician(@RequestParam(value="q") String technicianNric) {
		
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addSearchCriteria("likeNric", technicianNric);
		searchCriteria.addSearchCriteria("userType", SystemUser.USERTYPE_SECURITY_GUARD);
		searchCriteria.setSortType(SearchCriteria.SORTTYPE_ASC);
		searchCriteria.setSortName("nric");
		searchCriteria.setMaxRow(MAX_ROW);
		List<SystemUser> list = systemUserService.findUsers(searchCriteria);
		
		List<SystemUser> compact = new ArrayList<SystemUser>();
		if(list!=null)
		{
			for(int i=0;i<list.size();i++)
			{
				SystemUser tmp = list.get(i);
				SystemUser systemUser = new SystemUser();
				systemUser.setPersonName(tmp.getPersonName());
				systemUser.setNric(tmp.getNric());
				systemUser.setUserName(tmp.getUserName());
				
				compact.add(systemUser);
			}
		}
		
		return compact;
	}
	
	@RequestMapping(value="workOrder", method = RequestMethod.GET)
	public @ResponseBody WorkOrderWeek showWorkOrderService(@RequestParam(value="startDate",required=false) String txtStartDate,HttpServletRequest request) {
		
		WorkOrderWeek workOrderWeek = new WorkOrderWeek();
		
		DateTimeFormatter fmt = DateTimeFormat.forPattern(GlobalConstant.DATE_FORMAT_JAVA);
		DateTimeFormatter fmt2 = DateTimeFormat.forPattern("dd MMM");
		DateTimeFormatter fmt3 = DateTimeFormat.forPattern("dd");
		
		if(StringUtils.isEmpty(txtStartDate))
			txtStartDate = new LocalDate().toString(fmt);
		
		DateTime now = new DateTime();
		try{now = fmt.parseDateTime(txtStartDate);}catch(Exception e){}
		
		DateTime startDate = now.withDayOfWeek(DateTimeConstants.MONDAY);
		DateTime endDate = now.withDayOfWeek(DateTimeConstants.SUNDAY);
		
		workOrderWeek.setTitleWeek(startDate.toString(fmt2)+" -"+endDate.toString(fmt2));
		String []dateOfWeek = new String[7];
		String []shortDate = new String[7];
		Map []statusCount = new HashMap[7];
		
		workOrderWeek.setPrevDate(startDate.minusDays(1).toString(fmt));
		workOrderWeek.setNextDate(endDate.plusDays(1).toString(fmt));
		
		int i =0;
		Department department = getCurrentDepartment(request);
		Integer departmentId = null;
		if(department!=null)
			departmentId = department.getDepartmentId();
		List list = workOrderServiceFacade.getCountWorkOrderWeek(startDate.toDate(), endDate.toDate(),departmentId);
		while(startDate.getMillis()<=endDate.getMillis())
		{
			dateOfWeek[i] = startDate.toString(fmt);
			shortDate[i] = startDate.toString(fmt3);
			statusCount[i] = new HashMap<String, String>();
			
			if(list!=null)
			{
				for(int j=0;j<list.size();j++)
				{
					Object[] obj = (Object[]) list.get(j);
					Date bookingDate = (Date) obj[0];
					String strBookingDate = new LocalDate(bookingDate.getTime()).toString(fmt);
					
					if(StringUtils.equalsIgnoreCase(strBookingDate, dateOfWeek[i]))
					{
						String status = (String) obj[1];
						BigInteger count = (BigInteger) obj[2];		
						statusCount[i].put(status, count.intValue());
					}
					
				}
				
			}
			
			i++;
			startDate = startDate.plusDays(1);
		}
		
		workOrderWeek.setStatusCount(statusCount);
		workOrderWeek.setDateOfWeek(dateOfWeek);
		workOrderWeek.setShortDate(shortDate);
		
		return workOrderWeek;
	}
	
	@RequestMapping(value="workOrderHistory", method = RequestMethod.GET)
	public @ResponseBody List<WorkOrder> showWorkOrderHistory(@RequestParam(value="taxiNo",required=true) String taxiNo,@RequestParam(value="workOrderCode",required=false) String workOrderCode) {
		List<WorkOrder> workOrders = workOrderServiceFacade.findWorkOrdersHistory(taxiNo, workOrderCode);
		List<WorkOrder> compact = new ArrayList<WorkOrder>();
		if(workOrders!=null)
		{
			for(int i=0;i<workOrders.size();i++)
			{
				WorkOrder workOrder = workOrders.get(i);
				WorkOrder tmp = new WorkOrder();
				tmp.setWorkOrderId(workOrder.getWorkOrderId());
				tmp.setWorkOrderCode(workOrder.getWorkOrderCode());
				tmp.setDateBooking(workOrder.getDateBooking());
				tmp.setTechnician(workOrder.getTechnician());
				tmp.setDriverName(workOrder.getDriverName());
				compact.add(tmp);
			}
			
		}
		return compact; 
	}
	
	@RequestMapping(value="currentTime", method = RequestMethod.GET)
	public @ResponseBody String showCurrentTime() {
		
		DateTimeFormatter fmt = DateTimeFormat.forPattern("HH:mm:ss");
		return new LocalTime().toString(fmt);
	}
	
	@RequestMapping(value="showReportProcessingStatus/{reportId}", method = RequestMethod.GET)
	public @ResponseBody String showReportProcessingStatus(@PathVariable String reportId) {
		
		Report report = reportService.getReport(reportId);
		if(report!=null)
			return report.getReportStatus();

		return Report.REPORTSTATUS_FAIL;
	}
	
}
